#include <jni.h>
#include <string>
//#include "RTSP.h"
#include <android/native_window_jni.h>
#include "ffmpeg.h"
#include <thread>
#include <unistd.h>

extern "C" {
#include "include/libavformat/avformat.h"
#include "include/libavcodec/avcodec.h"
#include "include/libswscale/swscale.h"
#include "include/libavutil/imgutils.h"
#include "include/libavutil/opt.h"
#include "include/libavdevice/avdevice.h"
}

extern "C" JNIEXPORT jstring JNICALL
Java_com_claire_ffmpegplayer_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    av_register_all();
    avformat_network_init();
    return env->NewStringUTF(hello.c_str());
}

#define MAX_VIDEOS 32
ffmpeg *videos[MAX_VIDEOS];

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_claire_ffmpegplayer_sdk_FFmpeg_player_1Init(JNIEnv *env, jclass clazz) {
    ffmpeg::init();
    int j = 0;
    for (auto & item : videos){
        item = new ffmpeg;
        item->channel=j++;
    }
    return true;
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_claire_ffmpegplayer_sdk_FFmpeg_player_1Release(JNIEnv *env, jclass clazz) {
    // TODO: implement player_Release()
}


void* BusyLoopThread(void*) {
    volatile int i = 0;
    while (true) {
        sleep(1);
    }
    return nullptr;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_claire_ffmpegplayer_sdk_FFmpeg_player_1OpenStream(JNIEnv *env, jclass clazz, jstring url) {
    int length = env->GetStringUTFLength(url);
    if(length <= 0) {
        return -1;
    }
//    if(surface == NULL) {
//        return -1;
//    }
    for (auto & item : videos){
        if(!item->running) {
//            item->nativeWindow = ANativeWindow_fromSurface(env,surface);
//            if(item->nativeWindow == NULL) {
//                return -1;
//            }

            item->env = env;
            item->clazz = clazz;
            item->url = url;
            item->pUrl = env->GetStringUTFChars(item->url, 0);
            item->running = true;
//            pthread_t thread;
//            int ret = pthread_create(&thread, nullptr, BusyLoopThread, nullptr);
//            if (ret) {
//            }
//            item->openThread();
            pthread_t ntid;
            pthread_create(&ntid,NULL,_thread_t<ffmpeg,&ffmpeg::openStream>,(void *)item);
            LOGE("openThread")
//            std::thread t{&ffmpeg::openStream, &item};
//            std::thread(std::mem_fn(&ffmpeg::openStream),item);
//            std::thread t{&ffmpeg::openStream, &item};
//            std::thread t(threadVideo);
            return item->channel;
        }
    }
    return -1;
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_claire_ffmpegplayer_sdk_FFmpeg_player_1CloseStream(JNIEnv *env, jclass clazz,
                                                            jint channel) {
    // TODO: implement player_CloseStream()
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_claire_ffmpegplayer_sdk_FFmpeg_player_1SetSuface(JNIEnv *env, jclass clazz, jint channel,
                                                          jobject surface) {
    if(channel < 0 || channel >= MAX_VIDEOS) return false;
    if(videos[channel]->nativeWindow) {
        ANativeWindow_release(videos[channel]->nativeWindow);
    }
    videos[channel]->nativeWindow = ANativeWindow_fromSurface(env,surface);
    if(videos[channel]->nativeWindow) {
        return true;
    }
    return false;
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_claire_ffmpegplayer_sdk_FFmpeg_player_1RegisterCallback(JNIEnv *env, jclass clazz, jint channel,
                                                                 jobject listener) {
    if(listener == NULL) {
        return false;
    }
    if(channel < 0 || channel >= MAX_VIDEOS) return false;
    videos[channel]->callback = env->NewGlobalRef(listener);
}